import sys
from PySide2.QtWidgets import *
from PySide2.QtGui import *
from PySide2.QtCore import *
import json
import html

bracket = ['[', ']', '{', '}']
class CustomDelegate(QStyledItemDelegate):
    def paint(self, painter, option, index):
        painter.save()

        # 获取项的文本
        text = index.data(Qt.DisplayRole)
        rect = option.rect

        # 创建一个文本文档
        doc = QTextDocument()
        cursor = QTextCursor(doc)
        cursor.insertHtml(text)
        
        # 设置默认字体大小和加粗
        default_format = QTextCharFormat()
        default_format.setFontPointSize(12)  # 设置字体大小为12
        default_format.setFontWeight(QFont.Bold)
        doc.setDefaultFont(default_format.font())

        # 设置第一部分文本的颜色
        key_format = QTextCharFormat()
        key_format.setForeground(QColor("purple"))
        key_format.setFontWeight(QFont.Bold)
        
        # 设置第二部分文本的颜色
        val_format = QTextCharFormat()
        val_format.setForeground(QColor("green"))
        
        cmd_format = QTextCharFormat()
        cmd_format.setForeground(QColor("red"))
        
        chn_format = QTextCharFormat()
        chn_format.setForeground(QColor("blue"))
        
        cursor.setPosition(0)
        if text.strip() not in bracket:
            if ":" in text:
                split_index = text.find(":")
                cursor.movePosition(QTextCursor.Right, QTextCursor.KeepAnchor, split_index) 
                cursor.setCharFormat(key_format)
                if text[split_index+1:].strip() not in bracket:
                    cursor.setPosition(split_index + 1)
                    cursor.movePosition(QTextCursor.Right, QTextCursor.KeepAnchor, len(text) - split_index - 1) 
                    if '"cmd":' in text.lower():
                        cursor.setCharFormat(cmd_format)
                    elif '"channel":' in text.lower():
                        cursor.setCharFormat(chn_format)
                    else:
                        cursor.setCharFormat(val_format)

        # 如果当前项是选中项，则设置背景色为黄色
        if option.state & QStyle.State_Selected:
            painter.fillRect(option.rect, QColor(Qt.yellow))

        # 创建一个绘制器，并在指定的矩形中绘制文本
        painter.translate(rect.left(), rect.top())
        doc.drawContents(painter)

        painter.restore()

    def sizeHint(self, option, index):
        size = super().sizeHint(option, index)
        size.setHeight(size.height() + 5)  # 设置行间距为10个像素
        # 使用默认的大小提示
        return size

class CustomDialog(QDialog):
    def __init__(self, text):
        super().__init__()

        self.setWindowTitle("Custom Dialog")
        
        layout = QVBoxLayout()
        
        # 创建一个文本框并显示文本
        text_edit = QTextEdit()
        text_edit.setPlainText(text)
        text_edit.setReadOnly(True)  # 设置为只读
        
        layout.addWidget(text_edit)
        
        self.setLayout(layout)
        self.resize(1500, 400)
        self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)

class CustomTreeView(QTreeView):
    def __init__(self, parent=None):
        super().__init__(parent)
        
        # 设置为不可编辑
        # self.setEditTriggers(QTreeView.NoEditTriggers)
        self.setItemDelegate(CustomDelegate())
        self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)


    def mouseDoubleClickEvent(self, event):
        # 调用基类的方法以便处理默认行为
        super().mouseDoubleClickEvent(event)
        
        # 选中当前行的文本
        index = self.currentIndex()
        if index.isValid():
            item_text = index.data()
            if '"tracing":' in item_text:
                item_text = item_text.replace('"tracing": ', "", 1)
                item_text = eval(html.unescape(item_text))
                
                custom_dialog = CustomDialog(item_text)
                custom_dialog.exec_()       
            print("选中的文本:", item_text)
            


class JSONViewer(QWidget):
    def __init__(self, json_data, list_widget):
        super().__init__()
        self.json_data = json_data
        self.initUI()
        self.list_widget = list_widget

    def initUI(self):
        layout = QVBoxLayout()

        self.text_edit = CustomTreeView(self)
        layout.addWidget(self.text_edit)
        self.setLayout(layout)

        self.display_json()
        self.text_edit.expandAll()
        self.selection_model = self.text_edit.selectionModel()
        
    def sizeHint(self):
        if self.list_widget is not None:
            return QSize(self.list_widget.size().width(), 100)  # 设置一个固定的大小
        else:
            return QSize(900,900)

    def display_json(self):
        if self.json_data:
            formatted_json = json.dumps(self.json_data, indent=4)
            lines = formatted_json.split('\n')
            model = QStandardItemModel()
            parent_stk = [model]
            parent = model
            for item in lines:
                item = item.strip()
                if ": [" in item or item.strip() == "[" or ": {" in item or item.strip() == "{":
                    if item.find(r"{}") != -1 or item.find(r"[]") != -1:
                        parent.appendRow(QStandardItem(item))
                        continue
                    parent = QStandardItem(item)
                    parent_stk.append(parent)
                elif item.strip() == ']' or item.strip() == '}' or item.strip() == '],' or item.strip() == '},':
                    parent_stk.pop()
                    parent_stk[-1].appendRow(parent)
                    parent = parent_stk[-1]
                    parent.appendRow(QStandardItem(item))
                else:
                    parent.appendRow(QStandardItem(item))

            self.text_edit.setModel(model)

    def highLightKeyword(self, keyword):
        model = self.text_edit.model()
        self.selection_model.clearSelection()
        self.founded = False
        self.traverse_item(model.item(0), keyword)
        return self.founded
        
    def traverse_item(self, item: QStandardItem, keyword):
        if item is not None:
            if keyword in item.text():
                print("Item:", item.text())
                index = self.text_edit.model().indexFromItem(item)
                self.select_item(index)
                self.founded = True
            for row in range(item.rowCount()):
                child_item = item.child(row)
                self.traverse_item(child_item, keyword)
    
    def select_item(self, index):
        selection = QItemSelection()
        selection.select(index, index)
        self.selection_model.select(selection, QItemSelectionModel.Select)
        

def main():
    app = QApplication(sys.argv)
    with open("./tmp.json", "r") as file:
        json_data = json.load(file)
    viewer = JSONViewer(json_data)
    viewer.show()
    sys.exit(app.exec_())

if __name__ == "__main__":
    main()
